package com.android.webserver.tornado;

public class ThreadManager implements Runnable
{
	/** By default, wake up once per second. */
	private final static int	DEFAULT_SLEEP_TIME	= 1000;

	private final ServerPool	threadPool;
	private final int					sleepTime;

	/** Constructs the manager, using the specified values. */
	ThreadManager(ServerPool threadPool, int sleepTime)
	{
		this.threadPool = threadPool;
		this.sleepTime = sleepTime;
	}

	/**
	 * Constructs the manager, using the specified pool and the default sleep
	 * time.
	 */
	ThreadManager(ServerPool threadPool)
	{
		this(threadPool, DEFAULT_SLEEP_TIME);
	}

	/** Begin the infinite loop of sleeping and monitoring threads. */
	public void run()
	{
		while (true)
		{
			try
			{
				Thread.sleep(sleepTime);
			}
			catch (InterruptedException e)
			{
				/*
				 * A thread called interrupt() on us, so we wake up early and begin
				 * execution as normal. Currently, no code interrupts ThreadManager, but
				 * this may occur in the future.
				 */
			}

			int idleThreads = threadPool.getIdleThreads();
			int minIdleThreads = Tornado.config.getMinIdleThreads();
			int maxIdleThreads = Tornado.config.getMaxIdleThreads();
			Tornado.log.debug(idleThreads + " idle; " + threadPool.getBusyThreads()
					+ " busy");

			if (idleThreads < minIdleThreads)
			{
				// Spawn additional threads, as necessary
				spawnThreads(minIdleThreads - idleThreads);
			}
			else
				if (idleThreads > maxIdleThreads)
				{
					// Kill additional threads, as necessary
					killThreads(idleThreads - maxIdleThreads);
				}
		}
	}

	/**
	 * Spawns the specified number of <code>ServerThread</code>s and adds them to
	 * the <code>ServerPool</code.
	 * 
	 * @see tornado.ServerPool#addThread()
	 */
	private void spawnThreads(int num)
	{
		Tornado.log.debug(num + " new threads spawned");
		for (int i = 0; i < num; ++i)
		{
			threadPool.addThread();
		}
	}

	/**
	 * Kill the specified number of <code>ServerThread</code>s and removes them
	 * from the <code>ServerPool</code>.
	 * 
	 * @see tornado.ServerPool#removeThread()
	 */
	private void killThreads(int num)
	{
		Tornado.log.debug(num + " idle threads killed");
		for (int i = 0; i < num; ++i)
		{
			threadPool.removeThread();
		}
	}

}
